from django.http import Http404
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework_simplejwt.authentication import JWTAuthentication

from Contest.models import Contest
from Contest.serializers import ContestSerializer
from Person.authenticate import MyJSONWebTokenAuthentication
from Problems.serializers import ProblemSerializer
from Utils.BaseResponse import BaseResponse


# Create your views here.

class ContestAPIView(APIView):
    """
    获取或者添加 Contest 对象
    """
    authentication_classes = [MyJSONWebTokenAuthentication]  # 登录认证
    permission_classes = [IsAuthenticated]  # 配置了权限类，没登录的就没有权限访问了

    # GET 方法：获取所有 Contest 信息
    def get(self, request, format=None):
        """
       获取所有 Contest 对象
       :param request: 请求对象，包含客户端发起的HTTP请求信息
       :param format: 请求的数据格式，默认为None，允许客户端指定返回数据的格式
       :return: 返回一个包含所有Contest对象的列表，以及200 OK的状态码
       """

        contests = Contest.objects.all()
        serializer = ContestSerializer(contests, many=True)

        return BaseResponse(serializer.data, status=status.HTTP_200_OK).success()

    def post(self, request, format=None, *args, **kwargs):
        """
        创建一个新的Contest对象
        :param request: 请求对象，包含客户端提交的新Contest对象的数据
        :request.data 格式示例：
            {
                "title": "Weiqt的测试赛5",
                "description": "weiqt的测试比赛2",
                "begin_time": "2024-03-23T16:28:11",
                "end_time": "2024-09-26T04:00:00",
                "auth_type": "PASSWORD",
                "creator": 17
            }
        :return: 如果数据有效，则返回创建成功的Contest对象及其数据，以及201 CREATED的状态码；如果数据无效，则返回400 BAD REQUEST状态码和错误信息
        """

        serializer = ContestSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return BaseResponse(serializer.data, status=status.HTTP_201_CREATED).success()
        else:
            return BaseResponse(serializer.data, status=status.HTTP_400_BAD_REQUEST).fail("不合法的数据")


class ContestDetailAPIView(APIView):
    """
    检索或者更新一个 RemoteOJ 对象
    """

    authentication_classes = [MyJSONWebTokenAuthentication]  # 登录认证
    permission_classes = [IsAuthenticated]  # 配置了权限类，没登录的就没有权限访问了

    def check_user_exist(self, contest, request):
        pass

    def get_object(self, request, pk):
        try:
            contest = Contest.objects.get(pk=pk)
            return contest
        except Contest.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        """
          根据给定的主键(pk)获取单个 Contest 对象
          :param request: 请求对象，包含请求信息
          :param pk: 需要获取的 Contest 对象的主键
          :param format: 请求的数据格式，默认为None，允许客户端指定返回数据的格式
          :return: 若存在该 Contest 对象，则返回其序列化后的数据及200 OK状态码；若对象不存在，则返回404 NOT FOUND状态码及错误信息
        """
        try:
            contest = self.get_object(request, pk)
        except Http404:
            return BaseResponse(status=status.HTTP_404_NOT_FOUND).fail(f"对象不存在,不合法的 pk:{pk}")

        serializer = ContestSerializer(contest)
        return BaseResponse(serializer.data, status=status.HTTP_200_OK).success()

    def put(self, request, pk, format=None):
        """
        更新指定主键(pk)的 Contest 对象
        :param request: 请求对象，包含待更新的 Contest 对象数据
        :param pk: 需要更新的 Contest 对象的主键
        :param format: 请求的数据格式，默认为None，允许客户端指定发送数据的格式
        :return: 若更新成功，则返回更新后 Contest 对象的序列化数据及200 OK状态码；若对象不存在或数据不合法，则返回400 BAD REQUEST状态码及错误信息
        """
        try:
            contest = self.get_object(request, pk)
        except Http404:
            return BaseResponse(status=status.HTTP_404_NOT_FOUND).fail(f"对象不存在,不合法的 pk:{pk}")

        serializer = ContestSerializer(contest, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return BaseResponse(serializer.data, status=status.HTTP_200_OK).success()
        else:
            return BaseResponse(serializer.errors, status=status.HTTP_400_BAD_REQUEST).fail("不合法的数据")

    def delete(self, request, pk, format=None):
        """
        删除指定主键(pk)的 Contest 对象
        :param request: 请求对象，包含删除请求信息
        :param pk: 需要删除的 Contest 对象的主键
        :param format: 请求的数据格式，默认为None，此方法不受此参数影响
        :return: 若删除成功，则返回204 NO CONTENT状态码；若对象不存在，则返回404 NOT FOUND状态码及错误信息
        """
        try:
            contest = self.get_object(request, pk)
        except Http404:
            return BaseResponse(status=status.HTTP_404_NOT_FOUND).fail(f"对象不存在,不合法的 pk:{pk}")

        contest.delete()
        return BaseResponse(status=status.HTTP_204_NO_CONTENT).success()


class ContestDetail(APIView):
    authentication_classes = [MyJSONWebTokenAuthentication]  # 登录认证
    permission_classes = [IsAuthenticated]  # 配置了权限类，没登录的就没有权限访问了

    def post(self, request, ):
        pk = request.data.get('contestId')
        try:
            contest = Contest.objects.get(pk=pk)
        except Contest.DoesNotExist:
            return BaseResponse(status=status.HTTP_404_NOT_FOUND).fail("Contest not found")

        # 获取与contest关联的所有问题
        contest_problems = contest.problems.all()
        serializer = ProblemSerializer(contest_problems, many=True)

        return BaseResponse(data=serializer.data, status=status.HTTP_200_OK).success()
